home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Apple Game Sprockets / InputSprocket / Sample Drivers / Common Driver Code / ListUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-14  |  11.2 KB  |  575 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2.  
  3. File:      ListUtils.c
  4.  
  5. Copyright © 1996, 1997, 1998 Apple Computer, Inc., All Rights Reserved
  6.  
  7.  
  8. You may incorporate this sample code into your applications without
  9. restriction, though the sample code has been provided "AS IS" and the
  10. responsibility for its operation is 100% yours.  However, what you are
  11. not permitted to do is to redistribute the source as "DSC Sample Code"
  12. after having made changes. If you're going to re-distribute the source,
  13. we require that you make it clear in the source that the code was
  14. descended from Apple Sample Code, but that you've made changes.
  15.  
  16. *************************************************************************************/
  17.  
  18. #include <Memory.h>
  19. #include <string.h>
  20.  
  21. #include "ListUtils.h"
  22.  
  23. #if !__cplusplus && !__MWERKS__
  24. #define inline
  25. #endif
  26.  
  27. /*
  28. ************************************************************************
  29. ** inline functions
  30. ************************************************************************
  31. */
  32. inline void *
  33. MemAlloc( UInt32 inSize )
  34. {
  35.     return NewPtrClear( inSize );
  36. }
  37.  
  38. inline void
  39. MemFree( void *inPtr)
  40. {
  41.     DisposePtr( inPtr );
  42. }
  43.  
  44. /*
  45. ************************************************************************
  46. ** 
  47. ** Name: List_New
  48. **
  49. ** Description:
  50. **
  51. **    Allocate a new list.
  52. **
  53. ************************************************************************
  54. */
  55. List *
  56. List_New( void )
  57. {
  58.     List *theList;
  59.     
  60.     theList = MemAlloc( sizeof( List ) );
  61.     
  62.     return theList;
  63. }
  64.  
  65. /*
  66. ************************************************************************
  67. ** 
  68. ** Name: List_Dispose
  69. **
  70. ** Description:
  71. **
  72. **    Dispose of a list.  Will dispose of all list nodes that are still
  73. **    present in the list.
  74. **
  75. ************************************************************************
  76. */
  77. void
  78. List_Dispose(
  79.     List *inList
  80. )
  81. {
  82.     ListNode *theNode;
  83.     
  84.     /* empty the list of any nodes */
  85.     while( List_GetHead( inList ) )
  86.     {
  87.         theNode = List_RemoveHead( inList );
  88.         List_DisposeNode( theNode );
  89.     }
  90.     
  91.     /* delete the list */
  92.     MemFree( inList );
  93. }
  94.  
  95. /*
  96. ************************************************************************
  97. ** 
  98. ** Name: List_Initialize
  99. **
  100. ** Description:
  101. **
  102. **    Initialize list members.
  103. **
  104. ************************************************************************
  105. */
  106. void List_Initialize(
  107.     List *inList
  108. )
  109. {
  110.     inList->head =
  111.     inList->tail =
  112.     inList->curr = NULL;
  113.     
  114.     inList->iterationDirection = 0;
  115. }
  116.  
  117. /*
  118. ************************************************************************
  119. ** 
  120. ** Name: List_NewNode
  121. **
  122. ** Description:
  123. **
  124. **    Allocate a new list node and optionally place it at the head or
  125. **    tail of the list.
  126. **
  127. ************************************************************************
  128. */
  129. ListNode *
  130. List_NewNode(
  131.     List *inList,
  132.     ListNodeAddLocation inAddLocation
  133. )
  134. {
  135.     ListNode *theNode;
  136.     
  137.     theNode = MemAlloc( sizeof( ListNode ) );
  138.     if( theNode )
  139.     {
  140.         if( kListAddTail == inAddLocation )
  141.             List_AddTail( inList, theNode );
  142.         else if( kListAddHead == inAddLocation )
  143.             List_AddHead( inList, theNode );
  144.     }
  145.     
  146.     return theNode;
  147. }
  148.  
  149. /*
  150. ************************************************************************
  151. ** 
  152. ** Name: List_DisposeNode
  153. **
  154. ** Description:
  155. **
  156. **    Dispose of a list node.
  157. **
  158. ************************************************************************
  159. */
  160. void
  161. List_DisposeNode(
  162.     ListNode *inNode
  163. )
  164. {
  165.     MemFree( inNode );
  166. }
  167.  
  168. /*
  169. ************************************************************************
  170. ** 
  171. ** Name: List_GetHead
  172. **
  173. ** Description:
  174. **
  175. **    Return the node at the list head.
  176. **
  177. ************************************************************************
  178. */
  179. ListNode *
  180. List_GetHead(
  181.     List *inList
  182. )
  183. {
  184.     return inList->head;
  185. }
  186.  
  187. /*
  188. ************************************************************************
  189. ** 
  190. ** Name: List_GetTail
  191. **
  192. ** Description:
  193. **
  194. **    Return the node at the list tail.
  195. **
  196. ************************************************************************
  197. */
  198. ListNode *
  199. List_GetTail(
  200.     List *inList
  201. )
  202. {
  203.     return inList->tail;
  204. }
  205.  
  206. /*
  207. ************************************************************************
  208. ** 
  209. ** Name: List_AddToHead
  210. **
  211. ** Description:
  212. **
  213. **    Add a list node to the list head.
  214. **
  215. ************************************************************************
  216. */
  217. void
  218. List_AddHead(
  219.     List *inList,
  220.     ListNode *inNode
  221. )
  222. {
  223.     /* link in node */
  224.     inNode->next = inList->head;
  225.     inNode->prev = NULL;
  226.  
  227.     /* adjust head */
  228.     if( inList->head )
  229.         inList->head->prev = inNode;
  230.     inList->head = inNode;
  231.     
  232.     /* adjust tail */
  233.     if( NULL == inList->tail )
  234.         inList->tail = inNode;
  235. }
  236.  
  237. /*
  238. ************************************************************************
  239. ** 
  240. ** Name: List_AddToTail
  241. **
  242. ** Description:
  243. **
  244. **    Add a list node to the list tail.
  245. **
  246. ************************************************************************
  247. */
  248. void
  249. List_AddTail(
  250.     List *inList,
  251.     ListNode *inNode
  252. )
  253. {
  254.     /* link in node */
  255.     inNode->next = NULL;
  256.     inNode->prev = inList->tail;
  257.  
  258.     /* adjust tail */
  259.     if( inList->tail )
  260.         inList->tail->next = inNode;
  261.     inList->tail = inNode;
  262.     
  263.     /* adjust head */
  264.     if( NULL == inList->head )
  265.         inList->head = inNode;
  266. }
  267.  
  268. /*
  269. ************************************************************************
  270. ** 
  271. ** Name: List_RemoveHead
  272. **
  273. ** Description:
  274. **
  275. **    Remove the list head node.
  276. **
  277. ************************************************************************
  278. */
  279. void *
  280. List_RemoveHead(
  281.     List *inList
  282. )
  283. {
  284.     void *theData = NULL;
  285.     ListNode *theNode;
  286.     
  287.     theNode = inList->head;
  288.     if( theNode )
  289.     {
  290.         /* move to next node if this is the current one */
  291.         if( inList->iterationDirection && ( inList->curr == theNode ) )
  292.             List_Iterate( inList );
  293.             
  294.         /* remove head */
  295.         inList->head = theNode->next;
  296.         if( inList->head )
  297.             inList->head->prev = NULL;
  298.         
  299.         /* check tail */
  300.         if( inList->tail == theNode )
  301.             inList->tail = NULL;
  302.         
  303.         theData = theNode->data;
  304.         List_DisposeNode( theNode );
  305.     }
  306.         
  307.     return theData;
  308. }
  309.  
  310. /*
  311. ************************************************************************
  312. ** 
  313. ** Name: List_RemoveTail
  314. **
  315. ** Description:
  316. **
  317. **    Remove the list tail node.
  318. **
  319. ************************************************************************
  320. */
  321. void *
  322. List_RemoveTail(
  323.     List *inList
  324. )
  325. {
  326.     void *theData = NULL;
  327.     ListNode *theNode;
  328.     
  329.     theNode = inList->tail;
  330.     if( theNode )
  331.     {
  332.         /* move to next node if this is the current one */
  333.         if( inList->iterationDirection && ( inList->curr == theNode ) )
  334.             List_Iterate( inList );
  335.             
  336.         /* remove tail */
  337.         inList->tail = theNode->prev;
  338.         if( inList->tail )
  339.             inList->tail->next = NULL;
  340.         
  341.         /* check head */
  342.         if( inList->head == theNode )
  343.             inList->head = NULL;
  344.             
  345.         theData = theNode->data;
  346.         List_DisposeNode( theNode );
  347.     }
  348.         
  349.     return theData;
  350. }
  351.  
  352. /*
  353. ************************************************************************
  354. ** 
  355. ** Name: List_RemoveNode
  356. **
  357. ** Description:
  358. **
  359. **    Find the node in the list and remove it.
  360. **
  361. ************************************************************************
  362. */
  363. void *
  364. List_RemoveNode(
  365.     List *inList,
  366.     ListNode *inNode
  367. )
  368. {
  369.     void *theData = NULL;
  370.     ListNode *theNode;
  371.  
  372.     /* check head & tail */    
  373.     if( inList->head == inNode )
  374.         return List_RemoveHead( inList );
  375.     else if( inList->tail == inNode )
  376.         return List_RemoveTail( inList );
  377.         
  378.     theNode = inList->head->next;
  379.     while( theNode )
  380.     {
  381.         if( theNode == inNode )
  382.         {
  383.             /* move to next node if this is the current one */
  384.             if( inList->iterationDirection && ( inList->curr == theNode ) )
  385.                 List_Iterate( inList );
  386.                 
  387.             /* adjust links */
  388.             if( theNode->prev )
  389.                 theNode->prev->next = theNode->next;
  390.             if( theNode->next )
  391.                 theNode->next->prev = theNode->prev;
  392.             
  393.             theData = theNode->data;
  394.             List_DisposeNode( theNode );
  395.             
  396.             break;
  397.         }
  398.         
  399.         theNode = theNode->next;
  400.     }
  401.     
  402.     return theData;
  403. }
  404.  
  405. /*
  406. ************************************************************************
  407. ** 
  408. ** Name: List_RemoveNodeByData
  409. **
  410. ** Description:
  411. **
  412. **    Find the node in the list with the specified data and remove it.
  413. **
  414. ************************************************************************
  415. */
  416. void *
  417. List_RemoveNodeByData(
  418.     List *inList,
  419.     void *inNodeData
  420. )
  421. {
  422.     void *theData = NULL;
  423.     ListNode *theNode;
  424.  
  425.     /* check head & tail */    
  426.     if( inList->head->data == inNodeData )
  427.         return List_RemoveHead( inList );
  428.     else if( inList->tail->data == inNodeData )
  429.         return List_RemoveTail( inList );
  430.         
  431.     theNode = inList->head->next;
  432.     while( theNode )
  433.     {
  434.         if( theNode->data == inNodeData )
  435.         {
  436.             /* move to next node if this is the current one */
  437.             if( inList->iterationDirection && ( inList->curr == theNode ) )
  438.                 List_Iterate( inList );
  439.                 
  440.             /* adjust links */
  441.             if( theNode->prev )
  442.                 theNode->prev->next = theNode->next;
  443.             if( theNode->next )
  444.                 theNode->next->prev = theNode->prev;
  445.             
  446.             theData = theNode->data;
  447.             List_DisposeNode( theNode );
  448.             
  449.             break;
  450.         }
  451.         
  452.         theNode = theNode->next;
  453.     }
  454.     
  455.     return theData;
  456. }
  457.  
  458. /*
  459. ************************************************************************
  460. ** 
  461. ** Name: List_GetIterationState
  462. **
  463. ** Description:
  464. **
  465. **    Returns the iteration state of a list.  Useful to see if the list
  466. **    is already being iterated over.
  467. **
  468. ************************************************************************
  469. */
  470. ListIterationDirection
  471. List_GetIterationState(
  472.     List *inList
  473. )
  474. {
  475.     return inList->iterationDirection;
  476. }
  477.  
  478. /*
  479. ************************************************************************
  480. ** 
  481. ** Name: List_BeginIteration
  482. **
  483. ** Description:
  484. **
  485. **    Begin iteration over a list.  Will optionally block if the
  486. **    list is already being iterated over.
  487. **
  488. ************************************************************************
  489. */
  490. Boolean
  491. List_BeginIteration(
  492.     List *inList,
  493.     ListIterationDirection inIterateDirection,
  494.     Boolean inBlockWhileBusyFlag
  495. )
  496. {
  497.     if( inBlockWhileBusyFlag )
  498.     {
  499.         while( List_GetIterationState( inList ) )
  500.             /* empty body */;
  501.     }
  502. #if 0
  503.     // So, here's the problem:  If the inBlockWhileBusyFlag is true
  504.     // then you can never have nested traversals of this list.  However,
  505.     // if the block isn't preserved somehow then we're not thread safe.
  506.     // So, until someone figures out a way to take care of this we're
  507.     // just removing this clause and nested traversals will have the
  508.     // blocking flag set to false.
  509.     else if( inList->iterationDirection )
  510.     {
  511.         return false;
  512.     }
  513. #endif        
  514.     inList->iterationDirection = inIterateDirection;
  515.  
  516.     if( kListIterateForward == inIterateDirection )
  517.         inList->curr = inList->head;
  518.     else if( kListIterateBackward == inIterateDirection )
  519.         inList->curr = inList->tail;
  520.         
  521.     return true;
  522. }
  523.  
  524. /*
  525. ************************************************************************
  526. ** 
  527. ** Name: List_EndIteration
  528. **
  529. ** Description:
  530. **
  531. **    End iteration over a list, allowing others to access the list.
  532. **
  533. ************************************************************************
  534. */
  535. void
  536. List_EndIteration(
  537.     List *inList
  538. )
  539. {
  540.     inList->iterationDirection = kListNotIterating;
  541. }
  542.  
  543. /*
  544. ************************************************************************
  545. ** 
  546. ** Name: List_Iterate
  547. **
  548. ** Description:
  549. **
  550. **    Get the list node data for the current node, and move to the next
  551. **    node in the iteration direction.
  552. **
  553. ************************************************************************
  554. */
  555. void *
  556. List_Iterate(
  557.     List *inList
  558. )
  559. {
  560.     void *theData = NULL;
  561.     
  562.     if( inList->curr )
  563.     {
  564.         theData = inList->curr->data;
  565.         
  566.         if( kListIterateForward == inList->iterationDirection )
  567.             inList->curr = inList->curr->next;
  568.         else if( kListIterateBackward == inList->iterationDirection )
  569.             inList->curr = inList->curr->prev;
  570.         else
  571.             inList->curr = NULL;
  572.     }
  573.     
  574.     return theData;
  575. }